package com.corpgovernment.travelstandard.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

import com.corpgovernment.organization.constant.OrganizationResponseCodeEnum;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.corpgovernment.api.applytrip.apply.sync.StandardReserveTypeSyncRequest;
import com.corpgovernment.api.applytrip.metadata.UnLimitedTypeEnum;
import com.corpgovernment.api.applytrip.soa.request.QueryApplyTripStandardRequest;
import com.corpgovernment.api.applytrip.soa.response.QueryApplyTripStandardResponse;
import com.corpgovernment.api.organization.model.post.PostVo;
import com.corpgovernment.api.travelstandard.enums.*;
import com.corpgovernment.api.travelstandard.service.IMbTravelstandTrainService;
import com.corpgovernment.api.travelstandard.vo.*;
import com.corpgovernment.api.travelstandard.vo.TrainTravelStandardSoaVo.SeatVo;
import com.corpgovernment.api.travelstandard.vo.operate.TrainOperateLogVo;
import com.corpgovernment.api.travelstandard.vo.response.TrainTravelStandardShowTextResponse;
import com.corpgovernment.client.ManagementClientUtil;
import com.corpgovernment.common.base.JSONResult;
import com.corpgovernment.common.base.Page;
import com.corpgovernment.common.common.CorpBusinessException;
import com.corpgovernment.common.enums.ExceptionCodeEnum;
import com.corpgovernment.common.utils.ListUtils;
import com.corpgovernment.common.utils.ObjectUtils;
import com.corpgovernment.common.utils.PageUtils;
import com.corpgovernment.constants.TravelStandardOwnerTypeEnum;
import com.corpgovernment.dto.travelstandard.request.GetTravelStandardByTokenRequest;
import com.corpgovernment.dto.travelstandard.response.TravelStandardResponse;
import com.corpgovernment.dto.travelstandard.response.TravelStandardRuleVO;
import com.corpgovernment.dto.travelstandard.response.rule.ClassDiscountRuleVO;
import com.corpgovernment.dto.travelstandard.response.rule.ReserveRuleVO;
import com.corpgovernment.dto.travelstandard.response.rule.RuleChainVO;
import com.corpgovernment.organization.constant.OrganizationResponseCodeEnum;
import com.corpgovernment.organization.dataloader.ApplyTripClientLoader;
import com.corpgovernment.organization.service.IPostService;
import com.corpgovernment.organization.util.StrUtils;
import com.corpgovernment.travelstandard.entity.db.MbTravelstandTrain;
import com.corpgovernment.travelstandard.entity.db.TravelStandardPost;
import com.corpgovernment.travelstandard.mapper.MbTravelstandTrainMapper;
import com.corpgovernment.travelstandard.utils.BeanConverUtil;
import com.ctrip.corp.obt.generic.utils.CollectionUtils;
import com.ctrip.corp.obt.generic.utils.Conditional;
import com.ctrip.corp.obt.generic.utils.JsonUtils;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import com.ctrip.corp.obt.shard.context.PageContext;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class MbTravelstandTrainService extends TravelStandardBaseService implements IMbTravelstandTrainService {

    private final static String[] TRAIN_RC_TS_TEMP = {"trainRcTsTemp"};

    private final static String DISABLE = "N";

    @Autowired
    private MbTravelstandTrainMapper mbTravelstandTrainMapper;
    @Autowired
    private MbTravelstandReasonCodeService travelstandReasonCodeService;
    @Autowired
    private MbTravelstandTrainSeatService travelstandTrainSeatService;
    @Autowired
    private TravelStandardPostService travelStandardPostService;
    @Autowired
    private IPostService postService;
    @Autowired
    private TravelStandardPostService standPostService;

    @Autowired
    private ApplyTripClientLoader applyTripClientLoader;
    @Autowired
    private ManagementClientUtil managementClientUtil;


    @Override
    public void insert(MbTravelstandTrainVo model) {
        mbTravelstandTrainMapper.insertSelective(ObjectUtils.copyProperties(model, MbTravelstandTrain.class));
    }

    @Override
    public int delete(Long id) {
        return mbTravelstandTrainMapper.deleteByPrimaryKey(id);
    }

    @Override
    public int update(MbTravelstandTrainVo model) {
        return mbTravelstandTrainMapper
                .updateByPrimaryKeySelective(ObjectUtils.copyProperties(model, MbTravelstandTrain.class));
    }

    @Override
    public MbTravelstandTrainVo get(Long id) {
        return ObjectUtils.copyProperties(mbTravelstandTrainMapper.selectByPrimaryKey(id), MbTravelstandTrainVo.class);
    }

    @Override
    public Page page(MbTravelstandTrainVo model) {
        MbTravelstandTrain param = ObjectUtils.copyProperties(model, MbTravelstandTrain.class);
        PageContext.startPage(model.getPageNum(), model.getPageSize());
        List<MbTravelstandTrain> list = mbTravelstandTrainMapper.list(param);
        return PageUtils.optPageBy(list, MbTravelstandTrainVo.class);
    }

    @Transactional(rollbackFor = Exception.class)
    public void insertTravelstandTrain(MbTravelstandTrainVo model) {
        MbTravelstandTrain travelstandTrain = ObjectUtils.copyProperties(model, MbTravelstandTrain.class);
        travelstandTrain.setDatachangeCreatetime(new Date());
        travelstandTrain.setDatachangeLasttime(new Date());
        mbTravelstandTrainMapper.insert(travelstandTrain);
        model.setId(travelstandTrain.getId());

        // 从apollo获取折扣/舱等默认RC
        insertTravelstandReasonCode(TRAIN_RC_TS_TEMP, model.getId());
        // 批量插入坐席信息（默认全部选中）
        for (TrainSeatEnum trainSeatEnum : TrainSeatEnum.values()) {
            MbTravelstandTrainSeatVo travelstandTrainSeatVo = new MbTravelstandTrainSeatVo();
            travelstandTrainSeatVo.setTsTrainId(model.getId());
            travelstandTrainSeatVo.setSeatName(trainSeatEnum.getName());
            travelstandTrainSeatVo.setSeatCode(trainSeatEnum.getCode());
            travelstandTrainSeatService.insert(travelstandTrainSeatVo);
        }
        insertOperateLog(coverMbTravelstandTrainVoToTrainOperateLogVo(model));
    }

    @Transactional(rollbackFor = Exception.class)
    public JSONResult updateTravelStandardTrainProperty(TrainTravelStandardManageVo trainTravelStandardManageVo) {
        String jobScopeId = trainTravelStandardManageVo.getJobScopeId();
        if (StringUtils.isBlank(jobScopeId)) {
            return JSONResult.errorMsg("请选择职级范围");
        }
        String orgId = trainTravelStandardManageVo.getOrgId();
        if (StringUtils.isBlank(orgId)) {
            return JSONResult.errorMsg("组织id不能为空");
        }
        String id = trainTravelStandardManageVo.getId();
        if (StringUtils.isBlank(id)) {
            return JSONResult.errorMsg("差标id不能为空");
        }
        MbTravelstandTrainVo oriTravelstandTrainVo = get(Long.valueOf(id));
        if (oriTravelstandTrainVo == null) {
            return JSONResult.errorMsg("差标不存在！");
        }
        TrainOperateLogVo oriTrainOperateLogVo = coverMbTravelstandTrainVoToTrainOperateLogVo(oriTravelstandTrainVo);
        // 更新差标属性
        MbTravelstandTrainVo travelstandTrainVo = new MbTravelstandTrainVo(
                Long.valueOf(id),
                orgId,
                trainTravelStandardManageVo.getTitle(),
                trainTravelStandardManageVo.getSeatControl().getStatus(),
                trainTravelStandardManageVo.getSeatControl().getSeatRcSet(),
                trainTravelStandardManageVo.getSeatControl().getStcStatus(),
                trainTravelStandardManageVo.getSeatControl().getStcControlType(),
                trainTravelStandardManageVo.getSeatControl().getSubstituteTicketTrainNumber());
        travelstandTrainVo.setProductSwitch(trainTravelStandardManageVo.getProductSwitch());
        if (update(travelstandTrainVo) != 1) {
            return JSONResult.errorMsg("差标更新失败！");
        }
        // 可选坐席
        List<Node> seats = trainTravelStandardManageVo.getSeatControl().getSeatAvailabeList();
        // 删除旧坐席
        travelstandTrainSeatService.deleteByTsId(travelstandTrainVo.getId());
        // 循环插入选中坐席
        for (Node node : seats) {
            if (node.getIsChecked()) {
                MbTravelstandTrainSeatVo travelstandTrainSeatVo = new MbTravelstandTrainSeatVo();
                travelstandTrainSeatVo.setSeatCode(node.getCode());
                travelstandTrainSeatVo.setSeatName(node.getName());
                travelstandTrainSeatVo.setTsTrainId(travelstandTrainVo.getId());
                travelstandTrainSeatService.insert(travelstandTrainSeatVo);
            }
        }
        // 更新坐席RC
        RCListVo rcListVo = new RCListVo();
        rcListVo.setId(String.valueOf(travelstandTrainVo.getId()));
        rcListVo.setRcList(trainTravelStandardManageVo.getSeatControl().getSeatRcList());
        rcListVo.setRcType(ReasonCodeTypeEnum.TS.getCode());
        rcListVo.setTsType(TravelStandardTypeEnum.Train.getCode());
        travelstandReasonCodeService.updateTravelstandReasonCode(rcListVo);
        // 删除旧职位
        travelStandardPostService.deleteByTsidAndTsType(travelstandTrainVo.getId(),
                TravelStandardTypeEnum.Train.getCode());
        // 循环添加职位
        String[] jobIds = jobScopeId.split(",");
        for (String jobId : jobIds) {
            TravelStandardPostVo travelStandardPostVo = new TravelStandardPostVo();
            travelStandardPostVo.setPostid(Long.valueOf(jobId));
            travelStandardPostVo.setOrgid(travelstandTrainVo.getOrgId());
            travelStandardPostVo.setTsid(travelstandTrainVo.getId());
            travelStandardPostVo.setTstype(TravelStandardTypeEnum.Train.getCode());
            travelStandardPostVo.setTsname(travelstandTrainVo.getName());
            travelStandardPostService.insert(travelStandardPostVo);
        }
        updateOperateLog(
                oriTrainOperateLogVo,
                coverMbTravelstandTrainVoToTrainOperateLogVo(travelstandTrainVo));
        return JSONResult.ok();
    }

    @Transactional(rollbackFor = Exception.class)
    public JSONResult deleteTravelstandTrain(Long id) {
        MbTravelstandTrainVo oriMbTravelstandTrainVo = get(id);
        if (oriMbTravelstandTrainVo == null) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.TRAVEL_STAND_IS_NULL);
        }
        TrainOperateLogVo trainOperateLogVo = coverMbTravelstandTrainVoToTrainOperateLogVo(oriMbTravelstandTrainVo);
        // 删除差标
        delete(id);
        // 删除相关RC
        travelstandReasonCodeService.deleteByTsIdAndTsType(id, TravelStandardTypeEnum.Train.getCode());
        // 删除相关坐席
        travelstandTrainSeatService.deleteByTsId(id);
        // 删除相关职位关联
        travelStandardPostService.deleteByTsidAndTsType(id, TravelStandardTypeEnum.Train.getCode());
        deleteOperateLog(trainOperateLogVo, new TrainOperateLogVo());
        return JSONResult.ok();
    }

    public void updateStandardName(Long id, String title) {
        MbTravelstandTrainVo oriMbTravelstandTrainVo = get(id);
        if (oriMbTravelstandTrainVo == null) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.TRAVEL_STAND_IS_NULL);
        }
        TrainOperateLogVo oriTrainOperateLogVo = coverMbTravelstandTrainVoToTrainOperateLogVo(oriMbTravelstandTrainVo);
        update(new MbTravelstandTrainVo() {
            {
                setId(id);
                setName(title);
            }
        });
        TrainOperateLogVo trainOperateLogVo = ObjectUtils.copyProperties(oriTrainOperateLogVo, TrainOperateLogVo.class);
        trainOperateLogVo.setName(title);
        updateOperateLog(oriTrainOperateLogVo, trainOperateLogVo);
    }

    public List<TrainTravelStandardManageVo> listTravelstandTrain(MbTravelstandTrainVo model) {
        List<TrainTravelStandardManageVo> trainTravelStandardManageVos = new ArrayList<>();
        List<MbTravelstandTrainVo> travelstandTrainVos = ListUtils.copyList(
                mbTravelstandTrainMapper.list(ObjectUtils.copyProperties(model, MbTravelstandTrain.class)),
                MbTravelstandTrainVo.class);
        for (MbTravelstandTrainVo travelstandTrainVo : travelstandTrainVos) {
            // 获取相关职位
            List<TravelStandardPost> travelStandardPosts = travelStandardPostService.list(new TravelStandardPostVo() {
                {
                    setTsid(travelstandTrainVo.getId());
                    setTstype(TravelStandardTypeEnum.Train.getCode());
                }
            });
            // 获取相关rc
            List<MbTravelstandReasonCodeVo> travelstandReasonCodeVos =
                    travelstandReasonCodeService.list(new MbTravelstandReasonCodeVo() {
                        {
                            setTsId(travelstandTrainVo.getId());
                            setTsType(TravelStandardTypeEnum.Train.getCode());
                        }
                    });
            // 获取相关坐席
            List<MbTravelstandTrainSeatVo> travelstandTrainSeatVos =
                    travelstandTrainSeatService.list(new MbTravelstandTrainSeatVo() {
                        {
                            setTsTrainId(travelstandTrainVo.getId());
                        }
                    });
            trainTravelStandardManageVos.add(BeanConverUtil.travelstandTrainVoToTrainTravelStandardManageVo(
                    travelstandTrainVo,
                    ListUtils.copyList(travelStandardPosts, TravelStandardPostVo.class),
                    travelstandReasonCodeVos,
                    travelstandTrainSeatVos));
        }
        return trainTravelStandardManageVos;
    }

    public JSONResult<TrainTravelStandardShowVo> trainTravelStandardShowApp(String orgId, String uid, Long postId, Long trafficId,  String token) {
        if(StringUtils.isNotBlank(token)){
            return trainTravelStandardShowApp(token);
        }
        TrainTravelStandardShowVo travelStandard = null;
        if (Optional.ofNullable(trafficId)
                .isPresent()) {
            travelStandard =
                    this.trainTravelStandardByApplyNo(trafficId);
        }
        if (Objects.nonNull(travelStandard)) {
            return JSONResult.success(travelStandard);
        }
        TrainTravelStandardShowVo trainTravelStandardShowVo = new TrainTravelStandardShowVo();
        List<TrainTravelStandardShowVo.PolicyRuleVo> policyRuleVos = new ArrayList<>();
        TrainTravelStandardShowVo.PolicyRuleVo policyRuleVo = new TrainTravelStandardShowVo.PolicyRuleVo();
        policyRuleVo.setTitle("火车票");
        List<TrainTravelStandardShowVo.PolicyRuleVo.PolicyDetail> policyDetails = new ArrayList<>();
        MbTravelstandTrainVo travelstandTrainVo = getMbTravelstandTrainVoByuidAndOrgId(uid, orgId, postId);
        log.info("travelstandTrain  Vo:{}", JsonUtils.toJsonString(travelstandTrainVo));

        if (travelstandTrainVo == null) {
            TrainTravelStandardShowVo.PolicyRuleVo.PolicyDetail policyDetail2 =
                    new TrainTravelStandardShowVo.PolicyRuleVo.PolicyDetail();
            policyDetail2.setTitle("可选坐席");
            policyDetail2.setContent("不限");
            policyDetails.add(policyDetail2);
            TrainTravelStandardShowVo.PolicyRuleVo.PolicyDetail policyDetail3 =
                    new TrainTravelStandardShowVo.PolicyRuleVo.PolicyDetail();
            policyDetail3.setTitle("超标管控方式");
            policyDetail3.setContent("不限");
            policyDetails.add(policyDetail3);
        } else {
            // 处理产线开关未开的情况
            if (DISABLE.equals(travelstandTrainVo.getProductSwitch())){
                TrainTravelStandardShowVo.PolicyRuleVo.PolicyDetail policyDetail = new TrainTravelStandardShowVo.PolicyRuleVo.PolicyDetail();
                policyDetail.setTitle("产线管控");
                policyDetail.setContent("禁止预订");
                policyRuleVo.setPolicyDetail(Collections.singletonList(policyDetail));
                trainTravelStandardShowVo.setPolicyRule(Collections.singletonList(policyRuleVo));
                return JSONResult.success(trainTravelStandardShowVo);
            }
            // 拼装可选坐席
            if (TrainSwitchEnum.seatSwitch.E.getCode().equals(travelstandTrainVo.getSeatSwitch())) {
                TrainTravelStandardShowVo.PolicyRuleVo.PolicyDetail policyDetail2 =
                        new TrainTravelStandardShowVo.PolicyRuleVo.PolicyDetail();
                policyDetail2.setTitle("可选坐席");
                List<MbTravelstandTrainSeatVo> travelstandTrainSeatVos =
                        travelstandTrainSeatService.list(new MbTravelstandTrainSeatVo() {
                            {
                                setTsTrainId(travelstandTrainVo.getId());
                            }
                        });
                String content;
                try {
                    content = StrUtils.appendString(travelstandTrainSeatVos, MbTravelstandTrainSeatVo.class,
                            "seatName", ",", null, "");
                } catch (NoSuchFieldException | IllegalAccessException e) {
                    content = "";
                }
                policyDetail2.setContent(content);
                policyDetails.add(policyDetail2);
                TrainTravelStandardShowVo.PolicyRuleVo.PolicyDetail policyDetail3 =
                        new TrainTravelStandardShowVo.PolicyRuleVo.PolicyDetail();
                policyDetail3.setTitle("超标管控方式");
                String controlType = ControlTypeEnum.getEnumByCodeList(travelstandTrainVo.getControlType());
                policyDetail3.setContent(StringUtils.isEmpty(controlType) ? ControlTypeEnum.F.getName() : controlType);
                policyDetails.add(policyDetail3);
            } else if (TrainSwitchEnum.seatSwitch.N.getCode().equals(travelstandTrainVo.getSeatSwitch())) {
                TrainTravelStandardShowVo.PolicyRuleVo.PolicyDetail policyDetail2 =
                        new TrainTravelStandardShowVo.PolicyRuleVo.PolicyDetail();
                policyDetail2.setTitle("可选坐席");
                policyDetail2.setContent("不限");
                policyDetails.add(policyDetail2);
            }

            // 火车代取票差标是否开启
            if (Objects.equals(TrainSwitchEnum.seatSwitch.E.getCode(), travelstandTrainVo.getStcStatus())) {
                TrainTravelStandardShowVo.PolicyRuleVo.PolicyDetail policyDetail2 =
                        new TrainTravelStandardShowVo.PolicyRuleVo.PolicyDetail();
                policyDetail2.setTitle("代取票管控");
                policyDetail2.setContent("需预订代取票的车次");
                policyDetails.add(policyDetail2);
            }
        }
        policyRuleVo.setPolicyDetail(policyDetails);
        policyRuleVos.add(policyRuleVo);
        trainTravelStandardShowVo.setPolicyRule(policyRuleVos);
        log.info("trainTravelStandardShowVo:{}", JsonUtils.toJsonString(trainTravelStandardShowVo));
        return JSONResult.success(trainTravelStandardShowVo);
    }

    public JSONResult<TrainTravelStandardShowVo> trainTravelStandardShowApp(String token) {
        GetTravelStandardByTokenRequest request = new GetTravelStandardByTokenRequest();
        TrainTravelStandardShowVo trainTravelStandardShowVo = new TrainTravelStandardShowVo();
        TrainTravelStandardShowVo.PolicyRuleVo policyRuleVo = new TrainTravelStandardShowVo.PolicyRuleVo();
        policyRuleVo.setTitle("火车票");

        List<TrainTravelStandardShowVo.PolicyRuleVo.PolicyDetail> policyDetails = new ArrayList<>();
        request.setTokenList(Collections.singletonList(token));
        List<TravelStandardResponse> responseList = managementClientUtil.getTravelStandardByToken(request);
        if (CollectionUtils.isEmpty(responseList)){
            throw new CorpBusinessException(OrganizationResponseCodeEnum.TRAVEL_STAND_IS_NULL);
        }
        // 如果是出差申请单模式
        if (responseList.get(0).getTravelStandardToken().getOwnerType() == TravelStandardOwnerTypeEnum.TRAFFIC.getCode()) {
            // 出差申请单差标优先
            return JSONResult.success(trainTravelStandardByApplyNo(responseList.get(0).getRuleChain()));
        }

        if (Optional.ofNullable(responseList.get(0))
                        .map(TravelStandardResponse::getRuleChain)
                        .map(t -> CollectionUtils.isEmpty(t.getRuleList()))
                        .orElse(false)) {
            TrainTravelStandardShowVo.PolicyRuleVo.PolicyDetail policyDetail2 =
                    new TrainTravelStandardShowVo.PolicyRuleVo.PolicyDetail();
            policyDetail2.setTitle("可选坐席");
            policyDetail2.setContent("不限");
            policyDetails.add(policyDetail2);
            TrainTravelStandardShowVo.PolicyRuleVo.PolicyDetail policyDetail3 =
                    new TrainTravelStandardShowVo.PolicyRuleVo.PolicyDetail();
            policyDetail3.setTitle("超标管控方式");
            policyDetail3.setContent("不限");
            policyDetails.add(policyDetail3);
            policyRuleVo.setPolicyDetail(policyDetails);
            trainTravelStandardShowVo.setPolicyRule(Collections.singletonList(policyRuleVo));
            return JSONResult.success(trainTravelStandardShowVo);
        }

        RuleChainVO ruleChainVO = responseList.get(0).getRuleChain();
        // 处理产线开关未开的情况
        if (!ruleChainVO.getBookable()) {
            TrainTravelStandardShowVo.PolicyRuleVo.PolicyDetail policyDetail = new TrainTravelStandardShowVo.PolicyRuleVo.PolicyDetail();
            policyDetail.setTitle("产线管控");
            policyDetail.setContent("禁止预订");
            policyRuleVo.setPolicyDetail(Collections.singletonList(policyDetail));
            trainTravelStandardShowVo.setPolicyRule(Collections.singletonList(policyRuleVo));
            return JSONResult.success(trainTravelStandardShowVo);
        }
        List<TravelStandardRuleVO> travelStandardRuleVOS = ruleChainVO.getRuleList();

        ReserveRuleVO reserveRuleVO = (ReserveRuleVO) travelStandardRuleVOS.stream().filter(t -> "ReserveRule".equals(t.getName())).findFirst().orElse(null);
        if (reserveRuleVO == null) {
            return JSONResult.success(getTrainTravelStandardShowVo("不限", "不限"));
        } else {
            String content = "";
            String controlType = ControlTypeEnum.F.getName();
            if (Objects.nonNull(reserveRuleVO)) {
                content = Conditional.ofNullable(reserveRuleVO.getReserves())
                        .orElse(Collections.emptyMap())
                        .entrySet()
                        .stream().map(Map.Entry::getValue)
                        .collect(Collectors.joining(","));
                controlType =
                        ControlTypeEnum.getEnumByCodeList(reserveRuleVO.getRejectTypes()[0]);
                return JSONResult.success(getTrainTravelStandardShowVo(content, controlType));
            }

        }
        return JSONResult.success(trainTravelStandardShowVo);
    }

    public JSONResult<TrainTravelStandardShowSoaVo>
            trainTravelStandardShowSoa(TravelStandardSoaRequestVo travelStandardSoaRequestVo) {
        TrainTravelStandardShowSoaVo trainTravelStandardShowSoaVo = new TrainTravelStandardShowSoaVo();
        List<TrainTravelStandardShowSoaVo.PolicyRuleVo> policyRuleVos = new ArrayList<>();
        TrainTravelStandardShowSoaVo.PolicyRuleVo policyRuleVo = new TrainTravelStandardShowSoaVo.PolicyRuleVo();
        policyRuleVo.setTitle("火车票");
        List<TrainTravelStandardShowSoaVo.PolicyRuleVo.PolicyDetail> policyDetails = new ArrayList<>();
        MbTravelstandTrainVo travelstandTrainVo =
                getMbTravelstandTrainVoByuidAndOrgId(travelStandardSoaRequestVo.getUserId(),
                        travelStandardSoaRequestVo.getOrgId(), travelStandardSoaRequestVo.getPostId());
        if (travelstandTrainVo == null) {
            return JSONResult.success(null);
        } else {
            // 拼装可选坐席
            if (TrainSwitchEnum.seatSwitch.E.getCode().equals(travelstandTrainVo.getSeatSwitch())) {
                TrainTravelStandardShowSoaVo.PolicyRuleVo.PolicyDetail policyDetail2 =
                        new TrainTravelStandardShowSoaVo.PolicyRuleVo.PolicyDetail();
                policyDetail2.setTitle("可选坐席");
                List<MbTravelstandTrainSeatVo> travelstandTrainSeatVos =
                        travelstandTrainSeatService.list(new MbTravelstandTrainSeatVo() {
                            {
                                setTsTrainId(travelstandTrainVo.getId());
                            }
                        });
                String content;
                try {
                    content = StrUtils.appendString(travelstandTrainSeatVos, MbTravelstandTrainSeatVo.class,
                            "seatName", ",", null, "");
                } catch (NoSuchFieldException | IllegalAccessException e) {
                    content = "";
                }
                policyDetail2.setContent(content);
                policyDetails.add(policyDetail2);
            } else if (TrainSwitchEnum.seatSwitch.N.getCode().equals(travelstandTrainVo.getSeatSwitch())) {
                TrainTravelStandardShowSoaVo.PolicyRuleVo.PolicyDetail policyDetail2 =
                        new TrainTravelStandardShowSoaVo.PolicyRuleVo.PolicyDetail();
                policyDetail2.setTitle("可选坐席");
                policyDetail2.setContent("不限");
                policyDetails.add(policyDetail2);
            }
        }
        policyRuleVo.setPolicyDetail(policyDetails);
        policyRuleVos.add(policyRuleVo);
        trainTravelStandardShowSoaVo.setPolicyRule(policyRuleVos);
        return JSONResult.success(trainTravelStandardShowSoaVo);
    }

    public JSONResult<TrainTravelStandardShowTextResponse> trainTravelStandardShowText(String uid, String orgId) {
        TrainTravelStandardShowTextResponse trainTravelStandardShowTextResponse =
                new TrainTravelStandardShowTextResponse();
        MbTravelstandTrainVo travelstandTrainVo = getMbTravelstandTrainVoByuidAndOrgId(uid, orgId, null);
        if (travelstandTrainVo == null) {
            return JSONResult.success(null);
        }
        if ("N".equals(travelstandTrainVo.getProductSwitch())){
            String controlInfo = "产线管控：禁止预订";
            trainTravelStandardShowTextResponse.setControlInfos(Arrays.asList(controlInfo));
            return JSONResult.success(trainTravelStandardShowTextResponse);
        }
        // 设置坐席
        if (TrainSwitchEnum.seatSwitch.E.getCode().equals(travelstandTrainVo.getSeatSwitch())) {
            // 管控信息
            List<String> controlInfos = new ArrayList<>();
            List<MbTravelstandTrainSeatVo> travelstandTrainSeatVos = travelstandTrainSeatService.list(
                    new MbTravelstandTrainSeatVo().setTsTrainId(travelstandTrainVo.getId()));
            for (MbTravelstandTrainSeatVo travelstandTrainSeatVo : travelstandTrainSeatVos) {
                controlInfos.add(travelstandTrainSeatVo.getSeatName());
            }
            trainTravelStandardShowTextResponse.setControlInfos(controlInfos);
            // 管控rc信息
            List<String> controlRcInfos = new ArrayList<>();
            if (ControlTypeEnum.C.getCode().equals(travelstandTrainVo.getControlType())) {
                List<MbTravelstandReasonCodeVo> mbTravelstandReasonCodeVos = travelstandReasonCodeService.list(
                        new MbTravelstandReasonCodeVo()
                                .setTsId(travelstandTrainVo.getId())
                                .setTsRcType(ReasonCodeTypeEnum.TS.getCode())
                                .setIsChecked(true));
                for (MbTravelstandReasonCodeVo mbTravelstandReasonCodeVo : mbTravelstandReasonCodeVos) {
                    controlRcInfos.add(mbTravelstandReasonCodeVo.getName());
                }
            }
            trainTravelStandardShowTextResponse.setControlRcInfos(controlRcInfos);
        }
        return JSONResult.success(trainTravelStandardShowTextResponse);
    }

    /**
     * 根据uid和orgId获得对应火车差标
     *
     * @param uid
     * @param orgId 组织id，对应的组织类型可能是公司、部门。
     *              用于从mb_user_org_relation表中拿到对应的职级id
     * @return
     */
    public MbTravelstandTrainVo getMbTravelstandTrainVoByuidAndOrgId(String uid, String orgId, Long postId) {

        if (Objects.nonNull(postId) && postId > 0) {

        } else {
            if (StringUtils.isBlank(uid)) {
                throw new CorpBusinessException(OrganizationResponseCodeEnum.UID_NULL);
            }
            if (StringUtils.isBlank(orgId)) {
                throw new CorpBusinessException(OrganizationResponseCodeEnum.CORP_ID_ERROR);
            }
            // 根据uid和orgId查到对应职位
            PostVo postVo = postService.listPostByUidAndOrgId(uid, orgId);
            // 判断岗位是否存在
            if (postVo == null) {
                return null;
            }
            postId = postVo.getId();
        }

        // 根据职位查找对应机票差标
        TravelStandardPostVo vo = new TravelStandardPostVo();
        vo.setPostid(postId);
        vo.setTstype(TravelStandardTypeEnum.Train.getCode());
        List<TravelStandardPost> travelStandardPostVos = standPostService.list(vo);
        if (travelStandardPostVos == null || travelStandardPostVos.size() == 0) {
            return null;
        }
        TravelStandardPost travelStandardPost = travelStandardPostVos.get(0);
        // 获取对应差标
        Long tsId = travelStandardPost.getTsid();
        MbTravelstandTrainVo travelstandTrainVo = get(tsId);
        if (travelstandTrainVo == null) {
            return null;
        }
        return travelstandTrainVo;
    }

    /**
     * 将MbTravelstandTrainVo转换为TrainOperateLogVo
     */
    private TrainOperateLogVo coverMbTravelstandTrainVoToTrainOperateLogVo(MbTravelstandTrainVo mbTravelstandTrainVo) {
        if (mbTravelstandTrainVo != null) {
            TrainOperateLogVo trainOperateLogVo = new TrainOperateLogVo();
            trainOperateLogVo.setName(mbTravelstandTrainVo.getName());
            TrainSwitchEnum.seatSwitch seatSwitch =
                    TrainSwitchEnum.seatSwitch.getEnumByCode(mbTravelstandTrainVo.getSeatSwitch());
            trainOperateLogVo.setSeatSwitch(seatSwitch == null ? "" : seatSwitch.getName());
            ControlTypeEnum controlTypeEnum = ControlTypeEnum.getEnumByCode(mbTravelstandTrainVo.getControlType());
            trainOperateLogVo.setSeatControlType(controlTypeEnum == null ? "" : controlTypeEnum.getName());
            // 设置职级范围
            List<String> jobNames = travelStandardPostService.getJobNamesByTsIdAndTsType(mbTravelstandTrainVo.getId(),
                    TravelStandardTypeEnum.Train.getCode());
            StringBuilder jobScope = new StringBuilder();
            for (String jobName : jobNames) {
                jobScope.append(jobName);
                jobScope.append(",");
            }
            if (jobNames.size() > 0) {
                jobScope.deleteCharAt(jobScope.length() - 1);
            }
            trainOperateLogVo.setJobScope(jobScope.toString());
            // 设置坐席信息
            StringBuilder seatInfo = new StringBuilder();
            if (TrainSwitchEnum.seatSwitch.E.getCode().equals(mbTravelstandTrainVo.getSeatSwitch())) {
                List<MbTravelstandTrainSeatVo> mbTravelstandTrainSeatVos =
                        travelstandTrainSeatService.list(new MbTravelstandTrainSeatVo() {
                            {
                                setTsTrainId(mbTravelstandTrainVo.getId());
                            }
                        });
                for (MbTravelstandTrainSeatVo mbTravelstandTrainSeatVo : mbTravelstandTrainSeatVos) {
                    seatInfo.append(mbTravelstandTrainSeatVo.getSeatName());
                    seatInfo.append(",");
                }
                if (mbTravelstandTrainSeatVos.size() > 0) {
                    seatInfo.deleteCharAt(seatInfo.length() - 1);
                }
            }
            trainOperateLogVo.setSeatInfo(seatInfo.toString());
            // 坐席超标管控原因
            if (ControlTypeEnum.C.getCode().equals(mbTravelstandTrainVo.getControlType())) {
                List<MbTravelstandReasonCodeVo> mbTravelstandReasonCodeVos =
                        travelstandReasonCodeService.list(new MbTravelstandReasonCodeVo() {
                            {
                                setTsId(mbTravelstandTrainVo.getId());
                                setTsRcType(ReasonCodeTypeEnum.FC.getCode());
                            }
                        });
                StringBuilder seatControlRcs = new StringBuilder();
                for (MbTravelstandReasonCodeVo codeVo : mbTravelstandReasonCodeVos) {
                    seatControlRcs.append(codeVo.getName());
                    seatControlRcs.append(",");
                }
                if (mbTravelstandReasonCodeVos.size() > 0) {
                    seatControlRcs.deleteCharAt(seatControlRcs.length() - 1);
                }
                trainOperateLogVo.setSeatControlRcs(seatControlRcs.toString());
            }
            return trainOperateLogVo;
        }
        return null;
    }

    /**
     * 查询出差申请差标
     * @param trafficId
     * @return
     */
    private QueryApplyTripStandardResponse queryStandardInfo(Long trafficId) {
        QueryApplyTripStandardRequest request = new QueryApplyTripStandardRequest();
        request.setTrafficId(trafficId);
        QueryApplyTripStandardResponse response = applyTripClientLoader.queryStandardInfo(request);
        if (Objects.isNull(response)) {
            return null;
        }
        return response;
    }

    public TrainTravelStandardShowVo trainTravelStandardByApplyNo(RuleChainVO ruleChainVO) {
        List<TravelStandardRuleVO> travelStandardRuleVOS = ruleChainVO.getRuleList();
        if (CollectionUtils.isEmpty(travelStandardRuleVOS)){
            return getTrainTravelStandardShowVo("不限", "不限");
        }
        ReserveRuleVO reserveRuleVO = (ReserveRuleVO) travelStandardRuleVOS.stream().filter(t -> "ReserveRule".equals(t.getName())).findFirst().orElse(null);
        if (reserveRuleVO == null){
            return getTrainTravelStandardShowVo("不限", "不限");
        }
        String content = "";
        String controlType = ControlTypeEnum.F.getName();
        if (Objects.nonNull(reserveRuleVO)) {
            content = Conditional.ofNullable(reserveRuleVO.getReserves())
                    .orElse(Collections.emptyMap())
                    .entrySet()
                    .stream().map(Map.Entry::getValue)
                    .collect(Collectors.joining(","));

            controlType =
                    ControlTypeEnum.getEnumByCodeList(reserveRuleVO.getRejectTypes()[0]);
        }

        return getTrainTravelStandardShowVo(content, controlType);

    }
    public TrainTravelStandardShowVo trainTravelStandardByApplyNo(Long trafficId) {
        QueryApplyTripStandardResponse standardResponse = queryStandardInfo(trafficId);
        if (Objects.isNull(standardResponse) || BooleanUtils.isFalse(standardResponse.getEnable())) {
            return null;
        }

        if (UnLimitedTypeEnum.RESERVE.getValue().equals(standardResponse.getUnLimitedType())
                || UnLimitedTypeEnum.ALL.getValue().equals(standardResponse.getUnLimitedType())) {
            return getTrainTravelStandardShowVo("不限", "不限");
        }

        String content = "";
        String controlType = ControlTypeEnum.F.getName();
        if (Objects.nonNull(standardResponse.getStandardReserve())) {
            content = Optional.ofNullable(standardResponse.getStandardReserve().getReserveTypeList())
                    .orElse(Collections.emptyList())
                    .stream().map(StandardReserveTypeSyncRequest::getReserveName)
                    .collect(Collectors.joining(","));

            controlType =
                    ControlTypeEnum.getEnumByCodeList(standardResponse.getStandardReserve().getControlType());
        }

        return getTrainTravelStandardShowVo(content, controlType);

    }

    private TrainTravelStandardShowVo getTrainTravelStandardShowVo(String content, String controlType) {
        TrainTravelStandardShowVo trainTravelStandardShowVo = new TrainTravelStandardShowVo();
        List<TrainTravelStandardShowVo.PolicyRuleVo> policyRuleVos = new ArrayList<>();
        TrainTravelStandardShowVo.PolicyRuleVo policyRuleVo = new TrainTravelStandardShowVo.PolicyRuleVo();
        policyRuleVo.setTitle("火车票");
        List<TrainTravelStandardShowVo.PolicyRuleVo.PolicyDetail> policyDetails = new ArrayList<>();

        TrainTravelStandardShowVo.PolicyRuleVo.PolicyDetail policyDetail2 =
                new TrainTravelStandardShowVo.PolicyRuleVo.PolicyDetail();
        policyDetail2.setTitle("可选坐席");
        policyDetail2.setContent(content);
        policyDetails.add(policyDetail2);
        TrainTravelStandardShowVo.PolicyRuleVo.PolicyDetail policyDetail3 =
                new TrainTravelStandardShowVo.PolicyRuleVo.PolicyDetail();
        policyDetail3.setTitle("超标管控方式");
        policyDetail3.setContent(controlType);
        policyDetails.add(policyDetail3);
        policyRuleVo.setPolicyDetail(policyDetails);
        policyRuleVos.add(policyRuleVo);
        trainTravelStandardShowVo.setPolicyRule(policyRuleVos);
        return trainTravelStandardShowVo;
    }

    public TrainTravelStandardShowSoaVo trainTravelStandardShowSoa(Long trafficId) {
        QueryApplyTripStandardResponse standardResponse = queryStandardInfo(trafficId);
        if (Objects.isNull(standardResponse) || BooleanUtils.isFalse(standardResponse.getEnable())) {
            return null;
        }

        if (UnLimitedTypeEnum.RESERVE.getValue().equals(standardResponse.getUnLimitedType())
                || UnLimitedTypeEnum.ALL.getValue().equals(standardResponse.getUnLimitedType())) {
            return getTrainTravelStandardShowSoaVo("不限", "不限");
        }

        String content = "";
        String controlType = ControlTypeEnum.F.getName();
        if (Objects.nonNull(standardResponse.getStandardReserve())) {
            content = Optional.ofNullable(standardResponse.getStandardReserve().getReserveTypeList())
                    .orElse(Collections.emptyList())
                    .stream().map(StandardReserveTypeSyncRequest::getReserveName)
                    .collect(Collectors.joining(","));

            controlType =
                    ControlTypeEnum.getEnumByCodeList(standardResponse.getStandardReserve().getControlType());
        }

        return getTrainTravelStandardShowSoaVo(content, controlType);

    }

    private TrainTravelStandardShowSoaVo getTrainTravelStandardShowSoaVo(String content, String controlType) {
        TrainTravelStandardShowSoaVo result = new TrainTravelStandardShowSoaVo();
        List<TrainTravelStandardShowSoaVo.PolicyRuleVo> policyRuleVos = new ArrayList<>();
        TrainTravelStandardShowSoaVo.PolicyRuleVo policyRuleVo = new TrainTravelStandardShowSoaVo.PolicyRuleVo();
        policyRuleVo.setTitle("火车票");
        List<TrainTravelStandardShowSoaVo.PolicyRuleVo.PolicyDetail> policyDetails = new ArrayList<>();

        TrainTravelStandardShowSoaVo.PolicyRuleVo.PolicyDetail policyDetail2 =
                new TrainTravelStandardShowSoaVo.PolicyRuleVo.PolicyDetail();
        policyDetail2.setTitle("可选坐席");
        policyDetail2.setContent(content);
        policyDetails.add(policyDetail2);
        TrainTravelStandardShowSoaVo.PolicyRuleVo.PolicyDetail policyDetail3 =
                new TrainTravelStandardShowSoaVo.PolicyRuleVo.PolicyDetail();
        policyDetail3.setTitle("超标管控方式");
        policyDetail3.setContent(controlType);
        policyDetails.add(policyDetail3);
        policyRuleVo.setPolicyDetail(policyDetails);
        policyRuleVos.add(policyRuleVo);
        result.setPolicyRule(policyRuleVos);
        return result;
    }

    public TrainTravelStandardShowTextResponse trainTravelStandardShowText(Long trafficId) {
        QueryApplyTripStandardResponse standardResponse = queryStandardInfo(trafficId);
        if (Objects.isNull(standardResponse) || BooleanUtils.isFalse(standardResponse.getEnable())) {
            return null;
        }

        if (UnLimitedTypeEnum.RESERVE.getValue().equals(standardResponse.getUnLimitedType())
                || UnLimitedTypeEnum.ALL.getValue().equals(standardResponse.getUnLimitedType())) {
            return getTrainTravelStandardShowText(Lists.newArrayList("不限"), "不限");
        }

        List<String> controlRcInfos = Lists.newArrayList();
        String controlType = ControlTypeEnum.F.getName();
        if (Objects.nonNull(standardResponse.getStandardReserve())) {
            controlRcInfos = Optional.ofNullable(standardResponse.getStandardReserve().getReserveTypeList())
                    .orElse(Collections.emptyList())
                    .stream().map(StandardReserveTypeSyncRequest::getReserveName)
                    .collect(Collectors.toList());

            controlType =
                    ControlTypeEnum.getEnumByCodeList(standardResponse.getStandardReserve().getControlType());
        }

        return getTrainTravelStandardShowText(controlRcInfos, controlType);

    }

    private TrainTravelStandardShowTextResponse getTrainTravelStandardShowText(List<String> controlRcInfos,
            String controlType) {
        TrainTravelStandardShowTextResponse response = new TrainTravelStandardShowTextResponse();
        response.setControlInfos(Lists.newArrayList(controlType));
        response.setControlRcInfos(controlRcInfos);
        return response;
    }

    /**
     * 查询审批单号差标数据
     * @param trafficId
     * @return
     */
    public TrainTravelStandardSoaVo getTrainTravelStandard(Long trafficId) {
        QueryApplyTripStandardResponse standardResponse = queryStandardInfo(trafficId);
        if (Objects.isNull(standardResponse) || BooleanUtils.isFalse(standardResponse.getEnable())) {
            return null;
        }

        if (UnLimitedTypeEnum.RESERVE.getValue().equals(standardResponse.getUnLimitedType())
                || UnLimitedTypeEnum.ALL.getValue().equals(standardResponse.getUnLimitedType())) {
            TrainTravelStandardSoaVo trainTravelStandardSoaVo = new TrainTravelStandardSoaVo();
            SeatVo seatVo = new SeatVo();
            seatVo.setStatus("N");
            seatVo.setSeatAvailabeList(Collections.emptyList());
            seatVo.setSeatRcList(Lists.newArrayList());
            trainTravelStandardSoaVo.setSeatVo(seatVo);
            return trainTravelStandardSoaVo;
        }

        TrainTravelStandardSoaVo trainTravelStandardSoaVo = new TrainTravelStandardSoaVo();
        SeatVo seatVo = new SeatVo();
        seatVo.setStatus("E");
        seatVo.setSeatRcSet(standardResponse.getStandardReserve().getControlType());
        seatVo.setSeatRcList(Lists.newArrayList());
        seatVo.setSeatAvailabeList(Optional.ofNullable(standardResponse.getStandardReserve().getReserveTypeList())
                .orElse(Collections.emptyList()).stream()
                .map(v -> {
                    Node node = new Node();
                    node.setName(v.getReserveName());
                    node.setCode(v.getReserveCode());
                    node.setIsChecked(true);
                    return node;
                })
                .collect(Collectors.toList()));
        seatVo.setStcStatus("N");
        seatVo.setSubstituteTicketTrainNumber("N");
        trainTravelStandardSoaVo.setSeatVo(seatVo);
        return trainTravelStandardSoaVo;

    }
}
